<?php defined('IN_LK') or die('Access Denied');
/**
 * 加载模型
 * @access public
 * @param string $modelname 模型文件名 非完整文件名
 * @return resource
 */
function load_model($modelname)
{
	$model = load_class($modelname . '_model', 'models');
	if(!$model)
	{
		show_error('Call Undefined Model ' . $modelname);
	}
	return $model;
}
	
/**
 * 加载函数库 load_func
 * @access public
 * @param string $funcname 函数文件名 非完整文件名 .func.php
 * @param string $path 文件所在地址 地址相对于程序根目录
 * @return boolean
 */
function load_func($funcname, $path = '')
{
	static $funcs = array();
	if(!$path)
	{
		$path = 'libraries' . S . 'functions';
	}
	$key = md5($path . $funcname);
	if(isset($funcs[$key]) && $funcs[$key] === true)
	{
		return true;
	}
	foreach(array(SYS_PATH, APP_PATH) as $realpath)
	{
		$file = $realpath . $path . S . $funcname . '.func.php';
		if(is_file($file))
		{
			include $file;
			$funcs[$key] = true;
			return true;
		}
	}
	$funcs[$key] = false;
	return false;
}

/**
 * 加载基础类文件 load_class
 * @access public
 * @param string  $classname  类名{非文件名}
 * @param string  $path       类所在相对地址
 * @param boolean $initialize 是否自动加载
 * @return mixed 
 */
function load_class($classname, $path = '', $initialize = 1)
{
	static $classes = array();
	$realpath = $key = $file = '';
	if(!$path)
	{
		$path = 'libraries' . S . 'classes';
	}
	$key  = md5($path . $classname);
	if(isset($classes[$key]))
	{
		if($classes[$key] === true)
		{
			return true;
		}
		else
		{
			return $classes[$key];
		}
	}
	foreach(array(SYS_PATH, APP_PATH) as $realpath)
	{
		$file = $realpath . $path . S . $classname . '.class.php';
		if(is_file($file))
		{
			include $file;
			if($initialize && class_exists($classname))
			{
				$classes[$key] = new $classname;
			}
			else
			{
				$classes[$key] = false;
			}
			return $classes[$key];
		}
	}
	return false;
}

/**
 * 加载配置文件 load_config
 * @access public
 * @param string  $configname 配置文件名{非完整文件名}
 * @param string  $path       文件相对地址{包括文件名}
 * @param string  $key        配置数组的键值
 * @param boolean $reload     是否重新加载
 * @return mixed
 */
function load_config($configname, $key = '', $path = '', $reload = 0)
{
	static $configs = array();
	$file = $realfile = $realpath = '';
	if(!$reload && isset($configs[$configname]))
	{
		if(empty($key))
		{
			return $configs[$configname];
		}
		else if(isset($configs[$configname][$key]))
		{
			return $configs[$configname][$key];
		}
		else
		{
			return false;
		}
	}
	if(!$path)
	{
		$file = 'config' . S . $configname . '.config.php';
	}
	else
	{
		$file = $path . $configname . '.config.php';
	}
	foreach(array(SYS_PATH, APP_PATH) as $realpath)
	{
		$realfile = $realpath . $file;
		if(is_file($realfile))
		{
			$configs[$configname] = include $realfile;
			break;
		}
	}
	if(empty($key))
	{
		return isset($configs[$configname]) ? $configs[$configname] : false;
	}
	else if(isset($configs[$configname][$key]))
	{
		return $configs[$configname][$key];
	}
	else
	{
		return false;
	}
}

/**
 * 将错误写入日志文件
 * @access public
 * @param string $errno
 * @param string $errstr 
 * @param string $errfile
 * @param integer $errline
 * @param string $vars
 * @return boolean true
 */
function lk_error_handler($errno, $errstr, $errfile, $errline, $vars)
{
    load_func('dir');
    $dir = APP_PATH . 'log' . S . date('Ym', TIME) . S;
    $logfile = $dir . date('Ymd', TIME) . '.php';

	$date = date('Y-m-d/H:i:s', TIME);
	$errorPort = array(	
			E_ERROR           => 'Error',
			E_WARNING         => 'Warning',
			E_PARSE           => 'Parsing Error',
			E_NOTICE          => 'Notice',
			E_CORE_ERROR      => 'Core Error',
			E_CORE_WARNING    => 'Core Warning',
			E_COMPILE_ERROR   => 'Compile Error',
			E_COMPILE_WARNING => 'Compile Warning',
			E_USER_ERROR      => 'User Error',
			E_USER_WARNING    => 'User Warning',
			E_USER_NOTICE     => 'User Notice',
			E_STRICT          => 'Runtime Notice'
	);
	$user_error = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
	$err = array($date, $errno, $errorPort["$errno"], $errstr, $errfile, $errline);
	if(in_array($errno, $user_error))
	{
		$err['vars']= $vars;
	}
	if(!file_exists($logfile))
	{
		$fp = fopen($logfile, 'w');
		flock($fp, LOCK_EX);
		fwrite($fp, "<?php defined('IN_LK') or die('Access Denied');\n");
		flock($fp, LOCK_UN);
		fclose($fp);
	}
	$err = "\$logs[] = \"" . str_replace(array("\n", ' '), array('', ''), var_export($err, true)) . "\";\n";
	error_log($err, 3, $logfile);  //模式3，将错误日志写入文件
	@chmod($logfile, 0777);
	return true;
}

/**
 * 提示错误 show_error
 *
 */
function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
{
	echo show_error_handler($heading, $message, 'error_general', $status_code);
	exit;
}

function show_404($message = 'The page you requested was not found.', $status_code = 404, $heading = '404 Page Not Found')
{
	echo show_error_handler($heading, $message, 'error_404', $status_code);
	exit;
}

function show_error_handler($heading, $message, $template = 'error_general', $status_code = 500)
{
	set_status_header($status_code);
	$message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
	ob_start();
	include APP_PATH . 'errors' . S . $template . '.html';
	$buffer = ob_get_contents();
	ob_end_clean();
	return $buffer;
}

/**
 * Set HTTP Status Header
 *
 * @access	public
 * @param	int		the status code
 * @param	string
 * @return	void
 */
function set_status_header($code = 200, $text = '')
{
	$stati = array(
		200	=> 'OK',
		201	=> 'Created',
		202	=> 'Accepted',
		203	=> 'Non-Authoritative Information',
		204	=> 'No Content',
		205	=> 'Reset Content',
		206	=> 'Partial Content',
		
		300	=> 'Multiple Choices',
		301	=> 'Moved Permanently',
		302	=> 'Found',
		304	=> 'Not Modified',
		305	=> 'Use Proxy',
		307	=> 'Temporary Redirect',
		
		400	=> 'Bad Request',
		401	=> 'Unauthorized',
		403	=> 'Forbidden',
		404	=> 'Not Found',
		405	=> 'Method Not Allowed',
		406	=> 'Not Acceptable',
		407	=> 'Proxy Authentication Required',
		408	=> 'Request Timeout',
		409	=> 'Conflict',
		410	=> 'Gone',
		411	=> 'Length Required',
		412	=> 'Precondition Failed',
		413	=> 'Request Entity Too Large',
		414	=> 'Request-URI Too Long',
		415	=> 'Unsupported Media Type',
		416	=> 'Requested Range Not Satisfiable',
		417	=> 'Expectation Failed',
		
		500	=> 'Internal Server Error',
		501	=> 'Not Implemented',
		502	=> 'Bad Gateway',
		503	=> 'Service Unavailable',
		504	=> 'Gateway Timeout',
		505	=> 'HTTP Version Not Supported'
		);
	if($code == '' or !is_numeric($code))
	{
		show_error('Status codes must be numeric', 500);
	}
	if(isset($stati[$code]) and $text == '')
	{
		$text = $stati[$code];
	}
	if($text == '')
	{
		show_error('No status text available. Please check your status code number or supply your own message text.', 500);
	}
	$server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : false;
	if(substr(php_sapi_name(), 0, 3) == 'cgi')
	{
		header("Status: {$code} {$text}", true);
	}
	elseif($server_protocol == 'HTTP/1.1' or $server_protocol == 'HTTP/1.0')
	{
		header($server_protocol . " {$code} {$text}", true, $code);
	}
	else
	{
		header("HTTP/1.1 {$code} {$text}", true, $code);
	}
}

/**
 * 浏览器友好的变量输出
 *
 * @return null
 */
function dump($var, $echo = true, $label = null, $strict = true)
{
    $label = ($label===null) ? '' : rtrim($label) . ' ';
    if(!$strict)
	{
        if (ini_get('html_errors'))
		{
            $output = print_r($var, true);
            $output = "<pre>" . $label . htmlspecialchars($output, ENT_QUOTES) . "</pre>";
        }
		else
		{
            $output = $label . " : " . print_r($var, true);
        }
    }
	else
	{
        ob_start();
        var_dump($var);
        $output = ob_get_clean();
        if(!extension_loaded('xdebug'))
		{
            $output = preg_replace("/\]\=\>\n(\s+)/m", "] => ", $output);
            $output = '<pre>' . $label. htmlspecialchars($output, ENT_QUOTES) . '</pre>';
        }
    }
    if($echo)
	{
        echo $output;
        return null;
    }
	else
	{
        return $output;
	}
}


/**
 * 模板引擎函数 相当于$this->view();
 * @param string $filename 模板文件名
 * @param string $module   模板所属模块
 * @return string $cache_file 缓存文件路径
 */
function template($filename = 'index', $module = M)
{
	$template = load_class('template');
	$template_file = $template->path . $module . S . $filename . $template->ext;
	$cache_file    = $template->cache_path . $module . S . $filename . '.php';
	if(!is_file($template_file))
	{
		show_error("Template file \"$template_file\" not exists!", 500);
	}
	if(!is_file($cache_file) || @filemtime($cache_file) <@filemtime($template_file))
	{
		$template->template_compile($module, $filename);
	}
	return $cache_file;
}

/**
 * 解析出所用的时间和内存使用情况，
 * 然后与数据交换的伪变量
 *
 * @return string
 */
function becnhmark()
{
    $marker = array();
    if(load_config('app', 'enable_benchmark') === 0)
    {
        return $marker;
    }

    $benchmark = load_class('benchmark', 'core');
    $marker['elapsed'] = $benchmark->elapsed_time('total_execution_time_start', 'total_execution_time_end');
    $marker['memory']  = (!function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';
    return $marker;
}

function becnhmark_elapsed()
{
    $benchmark = becnhmark();
    return isset($benchmark['elapsed']) ? $benchmark['elapsed'] : false;
}

function becnhmark_memory()
{
    $benchmark = becnhmark();
    return isset($benchmark['memory']) ? $benchmark['memory'] : false;
}

/* End of file common.php */
/* Location: ./system/core/common.php */